New function to render a portion of a pixbuf to a drawable. Ignores alpha
authorFederico Mena Quintero <federico@redhat.com>
Thu, 28 Oct 1999 23:25:02 +0000 (23:25 +0000)
committerArturo Espinosa <unammx@src.gnome.org>
Thu, 28 Oct 1999 23:25:02 +0000 (23:25 +0000)
1999-10-28  Federico Mena Quintero  <federico@redhat.com>

* src/gdk-pixbuf-render.c (gdk_pixbuf_render_to_drawable): New
function to render a portion of a pixbuf to a drawable.  Ignores
alpha information and takes in a GC.
(gdk_pixbuf_render_to_drawable_alpha): New function to render a
portion of a pixbuf to a drawable.  It automatically creates a GC
and a clipping mask for alpha pixbufs.

gdk-pixbuf/ChangeLog
gdk-pixbuf/gdk-pixbuf.h
gdk/gdkpixbuf-render.c

index d01c3ef443a644a495ae2800bc9cd9a02693d78f..ec22354fcb4c088298588dea18bf57dbe984abaf 100644 (file)
@@ -1,3 +1,12 @@
+1999-10-28  Federico Mena Quintero  <federico@redhat.com>
+
+       * src/gdk-pixbuf-render.c (gdk_pixbuf_render_to_drawable): New
+       function to render a portion of a pixbuf to a drawable.  Ignores
+       alpha information and takes in a GC.
+       (gdk_pixbuf_render_to_drawable_alpha): New function to render a
+       portion of a pixbuf to a drawable.  It automatically creates a GC
+       and a clipping mask for alpha pixbufs.
+
 1999-10-28  Jonathan Blandford  <jrb@redhat.com>
 
        * src/gdk-pixbuf.h: turned convenience macros into convenience
index 5e517c070d139575eebe1566e9ac9a8b9e29c457..027a8fdeee9b6483270e05da77dde155785aabad 100644 (file)
@@ -97,15 +97,23 @@ void gdk_pixbuf_render_threshold_alpha (GdkPixbuf *pixbuf, GdkBitmap *bitmap,
                                        int width, int height,
                                        int alpha_threshold);
 
-void gdk_pixbuf_render_to_drawable (GdkPixbuf *pixbuf, GdkDrawable *drawable,
+void gdk_pixbuf_render_to_drawable (GdkPixbuf *pixbuf,
+                                   GdkDrawable *drawable, GdkGC *gc,
                                    int src_x, int src_y,
                                    int dest_x, int dest_y,
                                    int width, int height,
-                                   GdkPixbufAlphaMode alpha_mode,
-                                   int alpha_threshold,
                                    GdkRgbDither dither,
                                    int x_dither, int y_dither);
 
+void gdk_pixbuf_render_to_drawable_alpha (GdkPixbuf *pixbuf, GdkDrawable *drawable,
+                                         int src_x, int src_y,
+                                         int dest_x, int dest_y,
+                                         int width, int height,
+                                         GdkPixbufAlphaMode alpha_mode,
+                                         int alpha_threshold,
+                                         GdkRgbDither dither,
+                                         int x_dither, int y_dither);
+
 /* Transformations */
 #if 0
 GdkPixbuf *gdk_pixbuf_scale (const GdkPixbuf *pixbuf, gint w, gint h);
index 312f4b1833e1aecf6eae2f14c3265f8d0ef497ba..a12e8ae66a9b89c463c826a7ce46e66c9d3f606b 100644 (file)
  * @height: Height of region to threshold.
  * @alpha_threshold: Opacity values below this will be painted as zero; all
  * other values will be painted as one.
- * 
- * Takes the opacity values in a pixbuf and thresholds them to produce a
- * bi-level alpha mask that can be used as a clipping mask for a drawable.
+ *
+ * Takes the opacity values in a rectangular portion of a pixbuf and thresholds
+ * them to produce a bi-level alpha mask that can be used as a clipping mask for
+ * a drawable.
  **/
 void
 gdk_pixbuf_render_threshold_alpha (GdkPixbuf *pixbuf, GdkBitmap *bitmap,
@@ -119,23 +120,148 @@ gdk_pixbuf_render_threshold_alpha (GdkPixbuf *pixbuf, GdkBitmap *bitmap,
        gdk_gc_unref (gc);
 }
 
+\f
+
+/* Creates a buffer by stripping the alpha channel of a pixbuf */
+static guchar *
+remove_alpha (ArtPixBuf *apb, int x, int y, int width, int height, int *rowstride)
+{
+       guchar *buf;
+       int xx, yy;
+       guchar *src, *dest;
+
+       g_assert (apb->n_channels == 4);
+       g_assert (apb->has_alpha);
+       g_assert (x >= 0 && x + width <= apb->width);
+       g_assert (y >= 0 && y + height <= apb->height);
+
+       *rowstride = 4 * ((width * 3 + 3) / 4);
+
+       buf = g_new (guchar, *rowstride * height);
+
+       for (yy = 0; yy < height; yy++) {
+               src = apb->pixels + apb->rowstride * (yy + y) + x * apb->n_channels;
+               dest = buf + *rowstride * yy;
+
+               for (xx = 0; xx < width; xx++) {
+                       *dest++ = *src++;
+                       *dest++ = *src++;
+                       *dest++ = *src++;
+                       src++;
+               }
+       }
+
+       return buf;
+}
+
+/**
+ * gdk_pixbuf_render_to_drawable:
+ * @pixbuf: A pixbuf.
+ * @drawable: Destination drawable.
+ * @gc: GC used for rendering.
+ * @src_x: Source X coordinate within pixbuf.
+ * @src_y: Source Y coordinate within pixbuf.
+ * @dest_x: Destination X coordinate within drawable.
+ * @dest_y: Destination Y coordinate within drawable.
+ * @width: Width of region to render, in pixels.
+ * @height: Height of region to render, in pixels.
+ * @dither: Dithering mode for GdkRGB.
+ * @x_dither: X offset for dither.
+ * @y_dither: Y offset for dither.
+ * 
+ * Renders a rectangular portion of a pixbuf to a drawable while using the
+ * specified GC.  This is done using GdkRGB, so the specified drawable must have
+ * the GdkRGB visual and colormap.  Note that this function will ignore the
+ * opacity information for images with an alpha channel; the GC must already
+ * have the clipping mask set if you want transparent regions to show through.
+ **/
 void
-gdk_pixbuf_render_to_drawable (GdkPixbuf *pixbuf, GdkDrawable *drawable,
+gdk_pixbuf_render_to_drawable (GdkPixbuf *pixbuf,
+                              GdkDrawable *drawable, GdkGC *gc,
                               int src_x, int src_y,
                               int dest_x, int dest_y,
                               int width, int height,
-                              GdkPixbufAlphaMode alpha_mode,
-                              int alpha_threshold,
                               GdkRgbDither dither,
                               int x_dither, int y_dither)
 {
        ArtPixBuf *apb;
-       ArtIRect dest_rect, req_rect, area_rect;
-       GdkBitmap *bitmap;
-       GdkGC *gc;
        guchar *buf;
        int rowstride;
 
+       g_return_if_fail (pixbuf != NULL);
+       apb = pixbuf->art_pixbuf;
+       
+       g_return_if_fail (apb->format == ART_PIX_RGB);
+       g_return_if_fail (apb->n_channels == 3 || apb->n_channels == 4);
+       g_return_if_fail (apb->bits_per_sample == 8);
+
+       g_return_if_fail (drawable != NULL);
+       g_return_if_fail (gc != NULL);
+
+       g_return_if_fail (src_x >= 0 && src_x + width <= apb->width);
+       g_return_if_fail (src_y >= 0 && src_y + height <= apb->height);
+
+       /* This will have to be modified once libart supports other image types.
+        * Also, GdkRGB does not have gdk_draw_rgb_32_image_dithalign(), so we
+        * have to pack the buffer first.
+        */
+
+       if (apb->has_alpha)
+               buf = remove_alpha (apb, src_x, src_y, width, height, &rowstride);
+       else {
+               buf = apb->pixels + src_y * apb->rowstride + src_x * 3;
+               rowstride = apb->rowstride;
+       }
+
+       gdk_draw_rgb_image_dithalign (drawable, gc,
+                                     dest_x, dest_y,
+                                     width, height,
+                                     dither,
+                                     buf, rowstride,
+                                     x_dither, y_dither);
+
+       if (apb->has_alpha)
+               g_free (buf);
+}
+
+\f
+
+/**
+ * gdk_pixbuf_render_to_drawable_alpha:
+ * @pixbuf: A pixbuf.
+ * @drawable: Destination drawable.
+ * @src_x: Source X coordinate within pixbuf.
+ * @src_y: Source Y coordinates within pixbuf.
+ * @dest_x: Destination X coordinate within drawable.
+ * @dest_y: Destination Y coordinate within drawable.
+ * @width: Width of region to render, in pixels.
+ * @height: Height of region to render, in pixels.
+ * @alpha_mode: If the image does not have opacity information, this is ignored.
+ * Otherwise, specifies how to handle transparency when rendering.
+ * @alpha_threshold: If the image does have opacity information and @alpha_mode
+ * is GDK_PIXBUF_ALPHA_BILEVEL, specifies the threshold value for opacity
+ * values.
+ * @dither: Dithering mode for GdkRGB.
+ * @x_dither: X offset for dither.
+ * @y_dither: Y offset for dither.
+ *
+ * Renders a rectangular portion of a pixbuf to a drawable.  This is done using
+ * GdkRGB, so the specified drawable must have the GdkRGB visual and colormap.
+ **/
+void
+gdk_pixbuf_render_to_drawable_alpha (GdkPixbuf *pixbuf, GdkDrawable *drawable,
+                                    int src_x, int src_y,
+                                    int dest_x, int dest_y,
+                                    int width, int height,
+                                    GdkPixbufAlphaMode alpha_mode,
+                                    int alpha_threshold,
+                                    GdkRgbDither dither,
+                                    int x_dither, int y_dither)
+{
+       ArtPixBuf *apb;
+       GdkBitmap *bitmap;
+       GdkGC *gc;
+
        g_return_if_fail (pixbuf != NULL);
        apb = pixbuf->art_pixbuf;
 
@@ -163,15 +289,15 @@ gdk_pixbuf_render_to_drawable (GdkPixbuf *pixbuf, GdkDrawable *drawable,
 
                gdk_gc_set_clip_mask (gc, bitmap);
                gdk_gc_set_clip_origin (gc, dest_x, dest_y);
+               gdk_bitmap_unref (bitmap);
        }
 
-       /* Sigh, GdkRGB does not have gdk_draw_rgb_32_image_dithalign(), so we
-        * have to pack the buffer first.
-        */
-       if (apb->has_alpha) {
-//             buf = remove_alpha (apb, src_x, src_y, width, height, &rowstride);
-       } else {
-               buf = apb->pixels + src_y * apb->rowstride + src_x * 3;
-               rowstride = apb->rowstride;
-       }
+       gdk_pixbuf_render_to_drawable (pixbuf, drawable, gc,
+                                      src_x, src_y,
+                                      dest_x, dest_y,
+                                      width, height,
+                                      dither,
+                                      x_dither, y_dither);
+
+       gdk_gc_unref (gc);
 }